package service

import (
	"context"
	"errors"
	"gorm.io/gorm"
	"strconv"
	"strings"
	"time"
	"vrcm/src/vrcm/app/admin/models"
	"vrcm/src/vrcm/app/admin/models/likes"
	"vrcm/src/vrcm/common/service"

	"vrcm/src/vrcm/app/admin/service/dto/likes"
	"vrcm/src/vrcm/common/actions"
	cDto "vrcm/src/vrcm/common/dto"
)

type Likes struct {
	service.Service
}

// GetPage 获取Likes列表
func (e *Likes) GetPage(c *dto.LikesGetPageReq, p *actions.DataPermission, list *[]likes.Likes, count *int64) error {
	var err error
	var data likes.Likes

	err = e.Orm.Model(&data).
		Scopes(
			cDto.MakeCondition(c.GetNeedSearch()),
			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()),
			actions.Permission(data.TableName(), p),
		).
		Find(list).Limit(-1).Offset(-1).
		Count(count).Error
	if err != nil {
		e.Log.Errorf("LikesService GetPage error:%s \r\n", err)
		return err
	}
	return nil
}

// Get 获取Likes对象
func (e *Likes) Get(d *dto.LikesGetReq, p *actions.DataPermission, model *likes.Likes) error {
	var data likes.Likes

	err := e.Orm.Model(&data).
		Scopes(
			actions.Permission(data.TableName(), p),
		).
		First(model, d.GetId()).Error
	if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
		err = errors.New("查看对象不存在或无权查看")
		e.Log.Errorf("Service GetLikes error:%s \r\n", err)
		return err
	}
	if err != nil {
		e.Log.Errorf("db error:%s", err)
		return err
	}
	return nil
}

// Insert 创建Likes对象
func (e *Likes) Insert(c *dto.LikesInsertReq) error {
	var err error
	var data likes.Likes
	c.Generate(&data)
	err = e.Orm.Create(&data).Error
	if err != nil {
		e.Log.Errorf("LikesService Insert error:%s \r\n", err)
		return err
	}
	return nil
}

// Update 修改Likes对象
func (e *Likes) Update(c *dto.LikesUpdateReq, p *actions.DataPermission) error {
	var err error
	var data = likes.Likes{}
	e.Orm.Scopes(
		actions.Permission(data.TableName(), p),
	).First(&data, c.GetId())
	c.Generate(&data)

	db := e.Orm.Save(&data)
	if err = db.Error; err != nil {
		e.Log.Errorf("LikesService Save error:%s \r\n", err)
		return err
	}
	if db.RowsAffected == 0 {
		return errors.New("无权更新该数据")
	}
	return nil
}

// Remove 删除Likes
func (e *Likes) Remove(d *dto.LikesDeleteReq, p *actions.DataPermission) error {
	var data likes.Likes

	db := e.Orm.Model(&data).
		Scopes(
			actions.Permission(data.TableName(), p),
		).Delete(&data, d.GetId())
	if err := db.Error; err != nil {
		e.Log.Errorf("Service RemoveLikes error:%s \r\n", err)
		return err
	}
	if db.RowsAffected == 0 {
		return errors.New("无权删除该数据")
	}
	return nil
}

// SyncLikesNum 同步点赞数
func (e *Likes) SyncLikesNum() {
	tx := e.Orm.Begin()
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()
	// 创建一个上下文对象，并设置超时时间为5秒
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	tx.Statement.Context = ctx
	tx.Begin()
	if err := tx.Error; err != nil {
		e.Log.Errorf("tx error:%s \r\n", err)
		tx.Rollback()
		return
	}

	data := make([]likes.Likes, 0, 10)
	//获取redis缓存
	values, err := e.Redis.HGetAll(models.Prefix)
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("Service SyncLikesNum error:%s \r\n", err)
		return
	}

	ids := make([]int, 0, 10)
	for k, v := range values {
		num, _ := strconv.Atoi(v)
		like := likes.Likes{}
		like.LikeNum = num
		infos := strings.Split(k, models.Delimiter)
		if len(infos) < 3 {
			continue
		}
		like.TenantId = infos[0]
		id, _ := strconv.Atoi(infos[1])
		like.Id = id
		bindId, _ := strconv.Atoi(infos[2])
		like.BindId = bindId
		roundId, _ := strconv.Atoi(infos[3])
		like.RoundId = roundId
		like.UpdateTime = time.Now().Unix()
		if roundId <= 0 || bindId <= 0 || id <= 0 {
			continue
		}
		data = append(data, like)
		ids = append(ids, id)
	}

	var records []likes.Likes
	err = tx.Model(&likes.Likes{}).Where("id in ?", ids).Find(&records).Error
	if err != nil {
		e.Log.Errorf("get Likes error:%s \r\n", err)
		tx.Rollback()
		return
	}

	//获取直播间id
	for k, v := range data {
		for _, r := range records {
			if v.Id == r.Id {
				*(&data[k].LiveTime) = r.LiveTime
				*(&data[k].CreateTime) = r.CreateTime
			}
		}
	}

	err = tx.Model(&data).Save(&data).Error
	if err != nil {
		e.Log.Errorf("save Likes error:%s \r\n", err)
		tx.Rollback()
		return
	}

	tx.Commit()
	return
}

// GetLikesNum 获取点赞数
func (e *Likes) GetLikesNum(d *dto.GetLikesNumReq) (int, error) {

	var likes likes.Likes
	hk := models.Prefix
	filed := d.TenantId + models.Delimiter + strconv.Itoa(d.Id) + models.Delimiter + strconv.Itoa(d.BindId) + models.Delimiter + d.RoundId

	defer func() {
		if r := recover(); r != nil {
			e.Log.Errorf("GetLikesNum error:", r)
		}
	}()

	numString, err := e.Redis.HashGet(hk, filed)
	if err != nil {
		err = e.Orm.Where("id=?", d.Id).Find(&likes).Error
		if err != nil {
			e.Log.Errorf(err.Error())
			return 0, err
		}
		return likes.LikeNum, err
	}
	if numString == "" {
		numString = "0"
	}

	num, err := strconv.Atoi(numString)
	if err != nil {
		e.Log.Errorf(err.Error())
		return 0, err
	}
	return num, nil
}

// AddLikesNum 增加点赞数
func (e *Likes) AddLikesNum(d *dto.AddLikesNumReq) error {

	hk := models.Prefix
	//fmt.Println(d.TenantId + models.Delimiter + strconv.Itoa(d.Id) + models.Delimiter + strconv.Itoa(d.BindId) + models.Delimiter + d.RoundId)
	err := e.Redis.HIncrBy(hk, d.TenantId+models.Delimiter+strconv.Itoa(d.Id)+models.Delimiter+strconv.Itoa(d.BindId)+models.Delimiter+d.RoundId, d.LikeNum)
	e.Log.Trace("likes redis key:", d.TenantId+models.Delimiter+strconv.Itoa(d.Id)+models.Delimiter+strconv.Itoa(d.BindId)+models.Delimiter+d.RoundId, d.LikeNum)
	if err != nil {
		return err
	}
	return nil
}
